package com.health.common.service.util;

import com.health.common.common.ErrorCode;
import com.health.common.exception.BusinessException;
import com.health.common.service.config.SystemConfig;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.fisco.bcos.sdk.v3.client.Client;
import org.fisco.bcos.sdk.v3.codec.ContractCodecException;
import org.fisco.bcos.sdk.v3.crypto.keypair.CryptoKeyPair;
import org.fisco.bcos.sdk.v3.model.TransactionReceipt;
import org.fisco.bcos.sdk.v3.transaction.manager.AssembleTransactionProcessor;
import org.fisco.bcos.sdk.v3.transaction.manager.TransactionProcessorFactory;
import org.fisco.bcos.sdk.v3.transaction.model.exception.TransactionBaseException;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
@Slf4j
public class SDKUtils {

    @Resource
    private Client client;

    @Resource
    private SystemConfig config;

    public AssembleTransactionProcessor transactionProcessor(String privateKey) {
        String abi = config.getContract().getAbi();
        String bin = config.getContract().getBin();
        CryptoKeyPair cryptoKeyPair = client.getCryptoSuite().loadKeyPair(privateKey);
        return TransactionProcessorFactory.createAssembleTransactionProcessor(client, cryptoKeyPair, config.getContract().getContractName(), abi, bin);
    }

    public AssembleTransactionProcessor transactionProcessor() {
        String abi = config.getContract().getAbi();
        String bin = config.getContract().getBin();
        CryptoKeyPair cryptoKeyPair = client.getCryptoSuite().getCryptoKeyPair();
        return TransactionProcessorFactory.createAssembleTransactionProcessor(client, cryptoKeyPair, config.getContract().getContractName(), abi, bin);
    }

    public AssembleTransactionProcessor transactionProcessor(String contractName, String privateKey, String abi, String bin) {
        CryptoKeyPair cryptoKeyPair = client.getCryptoSuite().loadKeyPair(privateKey);
        return TransactionProcessorFactory.createAssembleTransactionProcessor(client, cryptoKeyPair, contractName, abi, bin);
    }

    public Object sendTransaction(String CONTRACT_NAME, String CONTRACT_ADDRESS, String funcName, List<Object> funcParams, String privateKey) throws TransactionBaseException, ContractCodecException {
        AssembleTransactionProcessor assembleTransactionProcessor = transactionProcessor(privateKey);
        TransactionReceipt transactionReceipt = assembleTransactionProcessor.sendTransactionAndGetReceiptByContractLoader(CONTRACT_NAME, CONTRACT_ADDRESS, funcName, funcParams);
        if (!transactionReceipt.isStatusOK()) {
            throw new BusinessException(ErrorCode.CONTRACT_ERROR, "区块链交易失败");
        }
        log.info("区块链交易成功{}，交易哈希为：{}", funcName, transactionReceipt.getTransactionHash());
        return transactionReceipt.getOutput();
    }

    public Object sendTransaction(String CONTRACT_NAME, String CONTRACT_ADDRESS, String funcName, List<Object> funcParams) throws TransactionBaseException, ContractCodecException {
        AssembleTransactionProcessor assembleTransactionProcessor = transactionProcessor();
        TransactionReceipt transactionReceipt = assembleTransactionProcessor.sendTransactionAndGetReceiptByContractLoader(CONTRACT_NAME, CONTRACT_ADDRESS, funcName, funcParams);
        if (!transactionReceipt.isStatusOK()) {
            throw new BusinessException(ErrorCode.CONTRACT_ERROR, "区块链交易失败");
        }
        log.info("区块链交易成功{}，交易哈希为：{}", funcName, transactionReceipt.getTransactionHash());
        return transactionReceipt.getOutput();
    }


}
